using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace VirtualScreenMaximizer
{
	public class Maximizer
	{
		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool UnregisterHotKey(IntPtr hWnd, int id);

		public static uint MOD_ALT = 0x1;
		public static uint MOD_CONTROL = 0x2;
		public static uint MOD_SHIFT = 0x4;
		public static uint MOD_WIN = 0x8;
		public static uint WM_HOTKEY = 0x312;

		public static Dictionary<int, string> keyAssignments = new Dictionary<int, string>();

		public static void RegisterHK(IntPtr handle, int hashCode, System.Windows.Forms.Keys key, uint modifiers, string command)
		{
			if (keyAssignments.ContainsKey(hashCode + (int) key))
			{
				return;
			}

			keyAssignments.Add(hashCode + (int) key, command);
			RegisterHotKey(handle, hashCode + (int) key, modifiers, (uint) key);

		}
		public static void UnRegisterHK(IntPtr handle, int hashCode, System.Windows.Forms.Keys key)
		{
			if (!keyAssignments.ContainsKey(hashCode + (int) key))
			{
				return;
			}
			keyAssignments.Remove(hashCode + (int) key);
			UnregisterHotKey(handle, hashCode + (int) key);
		}



		public static void ProcessHK(IntPtr wParam)
		{

			if (keyAssignments.ContainsKey(wParam.ToInt32()))
			{
				string command = keyAssignments [wParam.ToInt32()];
				//exec wparam
				Console.WriteLine("HotKey {0}", keyAssignments [wParam.ToInt32()]);
				//FullScreen
				switch (command)
				{

					case "FullScreen":
						Maximizer.FullScreen();
						break;
					case "RestoreOriginal":
						Maximizer.RestoreOriginal();
						break;
				}

			}

		}

		[DllImport("user32.dll")]
		static extern IntPtr GetForegroundWindow();
		[DllImport("user32.dll", SetLastError = true)]
		static extern int GetWindowLong(IntPtr hWnd, int nIndex);
		[DllImport("user32.dll")]
		static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
		[DllImport("user32.dll")]
		static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);


		static readonly int GWL_STYLE = (-16);
		/*static readonly int GWL_WNDPROC = (-4);
		static readonly int GWL_HINSTANCE = (-6);
		static readonly int GWL_HWNDPARENT = (-8);
		
		static readonly int GWL_EXSTYLE = (-20);
		static readonly int GWL_USERDATA = (-21);
		static readonly int GWL_ID = (-12);

		static readonly uint GW_HWNDFIRST = 0;
		static readonly uint GW_HWNDLAST = 1;
		static readonly uint GW_HWNDNEXT = 2;
		static readonly uint GW_HWNDPREV = 3;
		static readonly uint GW_OWNER = 4;
		static readonly uint GW_CHILD = 5;
		static readonly uint GW_ENABLEDPOPUP = 6;
		static readonly uint GW_MAX = 6;*/
		static readonly uint WS_MAXIMIZEBOX = 0x10000;


		public struct ConfiguredKey
		{
			public bool Alt;
			public bool Control;
			public bool Shift;
			public int KeyCode;
			public ConfiguredKey(bool a, bool c, bool s, int kc)
			{
				this.Alt = a;
				this.Control = c;
				this.Shift = s;
				this.KeyCode = kc;
			}
		}


		[StructLayout(LayoutKind.Sequential)]
		public struct WINDOWPLACEMENT
		{
			public int length;
			public int flags;
			public int showCmd;
			public System.Drawing.Point ptMinPosition;
			public System.Drawing.Point ptMaxPosition;
			public System.Drawing.Rectangle rcNormalPosition;

			public static WINDOWPLACEMENT Default
			{
				get
				{
					WINDOWPLACEMENT result = new WINDOWPLACEMENT();
					result.length = Marshal.SizeOf(result);
					return result;
				}
			}
		}

		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
		[DllImport("user32.dll")]
		static extern bool SetWindowPlacement(IntPtr hWnd,[In] ref WINDOWPLACEMENT lpwndpl);





		private static Dictionary<IntPtr, int> originalWinLongs = new Dictionary<IntPtr, int>();
		private static Dictionary<IntPtr, WINDOWPLACEMENT> originalWindowPlacements = new Dictionary<IntPtr, WINDOWPLACEMENT>();

		private static void FullScreen()
		{
			IntPtr fw = GetForegroundWindow();
			int lngStyle = GetWindowLong(fw, GWL_STYLE);
			if (!originalWinLongs.ContainsKey(fw))
			{
				originalWinLongs.Add(fw, lngStyle);
				
			}


			WINDOWPLACEMENT wp=new WINDOWPLACEMENT();
			GetWindowPlacement(fw, ref wp);

			if (!originalWindowPlacements.ContainsKey(fw))
			{
				originalWindowPlacements.Add(fw, wp);
			}

			lngStyle = (int) (lngStyle & ~WS_MAXIMIZEBOX);
			lngStyle = (int) (lngStyle & ~0xC00000);
			System.Drawing.Rectangle vSize = System.Windows.Forms.SystemInformation.VirtualScreen;

			SetWindowLong(fw, GWL_STYLE, (IntPtr) lngStyle);

			SetWindowPos(fw, IntPtr.Zero, vSize.Left, vSize.Top, vSize.Width, vSize.Height, 0);
		}

		private static void RestoreOriginal()
		{
			IntPtr fw = GetForegroundWindow();
			if (originalWinLongs.ContainsKey(fw))
			{
				SetWindowLong(fw, GWL_STYLE, (IntPtr) originalWinLongs [fw]);
			}

			if (originalWindowPlacements.ContainsKey(fw))
			{
				WINDOWPLACEMENT wp=originalWindowPlacements[fw];
				SetWindowPlacement(fw, ref wp);
			}
		}



	}
}
